package com.agrm.utils;

import com.agrm.model.member.pojo.Member;
import com.agrm.model.user.pojo.User;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Map;
import java.util.Objects;


/**
 * JWT工具类，用于生成JSON Web Token (JWT)
 */
public class JwtUtil {
    public static String encode(String jwtId, User user, Map<String, Object> payloads, Instant expireTime, String secret) {
        Objects.requireNonNull(secret, "加密密钥不可为空");
        JWTCreator.Builder builder = JWT.create();
        if (payloads != null) {
            builder.withPayload(payloads);
        }
        if (expireTime != null) {
            builder.withExpiresAt(expireTime);//过期时间
        }

        //颁发时间
        builder.withIssuedAt(Instant.now());
        //主题
        builder.withSubject("login");
        //发行人
        builder.withIssuer("agrm");
        //用户
        builder.withAudience(user.getUsername());
        builder.withClaim("userId", user.getId());//用户编号，主键

        //builder.withNotBefore(Instant.now());
        builder.withJWTId(jwtId);

        return builder.sign(Algorithm.HMAC256(secret));
    }
    public static String encode(String jwtId, Member member, Map<String, Object> payloads, Instant expireTime, String secret) {
        Objects.requireNonNull(secret, "加密密钥不可为空");

        JWTCreator.Builder builder = JWT.create();
        if (payloads != null) {
            builder.withPayload(payloads);
        }
        if (expireTime != null) {
            builder.withExpiresAt(expireTime);//过期时间
        }

        //颁发时间
        builder.withIssuedAt(Instant.now());
        //主题
        builder.withSubject("login");
        //发行人
        builder.withIssuer("agrm");
        //用户
        builder.withAudience(member.getAccount());
        builder.withClaim("memberId", member.getId());//用户编号，主键

        //builder.withNotBefore(Instant.now());
        builder.withJWTId(jwtId);

        return builder.sign(Algorithm.HMAC256(secret));
    }

    public static String encode(String jwtId, User user, int minutes, String secret) {
        if (minutes < 0) {
            throw new RuntimeException("有效时长必须大于等于0");
        }
        Map<String, Object> payloads = Map.of();
        //失效时间
        Instant expireTime = LocalDateTime.now().plusMinutes(minutes).atZone(ZoneId.systemDefault()).toInstant();

        return encode(jwtId, user, payloads, expireTime, secret);
    }
    public static String encode(String jwtId, Member member, int minutes, String secret) {
        if (minutes < 0) {
            throw new RuntimeException("有效时长必须大于等于0");
        }
        Map<String, Object> payloads = Map.of();
        //失效时间
        Instant expireTime = LocalDateTime.now().plusMinutes(minutes).atZone(ZoneId.systemDefault()).toInstant();

        return encode(jwtId, member, payloads, expireTime, secret);
    }

    /**
     * 解码
     *
     * @param token  jwt
     * @param secret 密钥
     * @return 解密之后的token
     */
    public static DecodedJWT decode(String token, String secret) {
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(secret)).build();
        return jwtVerifier.verify(token);
    }
    /**
     * 创建JWT令牌
     *
     * @param username 用户名
     * @param id JWT的唯一标识符
     * @param payloads JWT的负载信息（自定义数据）
     * @param expireTime 过期时间
     * @param secretKey 签名密钥
     * @return 生成的JWT字符串
     */
    public static String createJwt(String username, String id, Map<String, Object> payloads, LocalDateTime expireTime, String secretKey) {
        // 创建JWT构建器
        JWTCreator.Builder builder = JWT.create();
        String jwt = builder.withPayload(payloads).withExpiresAt(expireTime.toInstant(ZoneOffset.of("+8")))
                .withIssuer("STMall").withIssuedAt(Instant.now()).withSubject("用户认证").withAudience(username).withJWTId(id).sign(Algorithm.HMAC256(secretKey));
        return jwt;
    }
}
